package com.genexususa.eo.bing.connection;

import com.genexususa.eo.bing.CampaignManagementServiceClasses.*;
import com.genexususa.eo.bing.data.GxException;
import com.genexususa.eo.bing.data.GxItemException;
import com.genexususa.eo.bing.data.Info;
import com.genexususa.eo.bing.data.Util;
import com.genexususa.eo.bing.data.requests.GxAdGroupAdRotationsRequest;
import com.genexususa.eo.bing.data.requests.GxAdGroupNegativeKeywordsRequest;
import com.genexususa.eo.bing.data.requests.GxAdGroupNegativeSitesRequest;
import com.genexususa.eo.bing.data.requests.GxAdGroupsRequest;
import com.genexususa.eo.bing.data.results.GxAdGroupsResult;
import com.genexususa.eo.bing.data.results.GxAdGroupsResults;
import com.genexususa.eo.bing.data.wsSubclasses.GxAdGroup;
import com.genexususa.eo.bing.data.wsSubclasses.GxAdGroupAdRotation;
import com.genexususa.eo.bing.data.wsSubclasses.GxAdGroupNegativeKeywords;
import com.genexususa.eo.bing.data.wsSubclasses.GxAdGroupNegativeSites;
import com.genexususa.eo.bing.test.TestUtil;
import com.genexususa.eo.google.data.*;
import com.genexususa.eo.google.data.Error;
import org.xml.sax.SAXException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.rpc.ServiceException;
import java.io.IOException;
import java.io.StringWriter;
import java.rmi.RemoteException;
import java.util.HashMap;

public class AdGroupManager {
    public AdGroupManager() {
    }

    public String addAdGroups(long customerAccountId, String adGroupsRequestsXML) {
        ICampaignManagementService campaignManagement = null;
        CampaignManagementServiceLocator campaignServiceLocator = null;
        BasicHttpBinding_ICampaignManagementServiceStub stub = null;
        AddAdGroupsRequest addAdGroupsRequest = null;
        AddAdGroupsResponse addAdGroupsResponse = null;
        GA_Result result = new GA_Result();
        Util util = new Util();
        GxAdGroupsRequest[] adGroupsRequests = null;
        try {
            HashMap<String, String> properties = Info.getBingProperties();
            String namespace = properties.get("campaignNamespace");
            String url = properties.get("campaignURL");
            String userName = properties.get("username");
            String password = properties.get("password");
            String developerToken = properties.get("developerToken");
            String customerId = properties.get("customerId");
            String applicationToken = properties.get("applicationToken");

            campaignServiceLocator = new CampaignManagementServiceLocator();
            campaignServiceLocator.setBasicHttpBinding_ICampaignManagementServiceEndpointAddress(url);
            campaignManagement = campaignServiceLocator.getBasicHttpBinding_ICampaignManagementService(); // ServiceException
            stub = (BasicHttpBinding_ICampaignManagementServiceStub) campaignManagement;

            // Set header parameters
            stub.setHeader(namespace, "UserName", userName);
            stub.setHeader(namespace, "Password", password);
            stub.setHeader(namespace, "DeveloperToken", developerToken);
            stub.setHeader(namespace, "CustomerId", customerId);
            stub.setHeader(namespace, "CustomerAccountId", customerAccountId);
            stub.setHeader(namespace, "ApplicationToken", applicationToken);

            // Parse adGroupsRequests from XML
            adGroupsRequests = util.adGroupsRequestsFromXML(adGroupsRequestsXML); // IllegalArgumentException, GxException, ParserConfigurationException, SAXException, IOException
            if (adGroupsRequests.length == 0) {
                throw new GxItemException("No AdGroupsRequests were found");
            }

            for (int j=0; j<adGroupsRequests.length; j++) {
                // Set body parameters
                addAdGroupsRequest = new AddAdGroupsRequest();
                addAdGroupsRequest.setCampaignId(adGroupsRequests[j].getBingCampaignId());
                //addAdGroupsRequest.setAdGroups(adGroupsRequests[j].getAdGroups());

                try {
                    // Call WS
                    //addAdGroupsResponse = campaignManagement.addAdGroups(addAdGroupsRequest); // RemoteException, ApiFaultDetail, AdApiFaultDetail

                    AdGroup[] allAdGroups = adGroupsRequests[j].getAdGroups();
                    AdGroup[] chunkedAdGroups = null;
                    // max element limit = 1000
                    int chunks = (int)Math.ceil(allAdGroups.length / 1000.0);
                    if (chunks <= 1){
                        addAdGroupsRequest.setAdGroups(allAdGroups);
                        addAdGroupsResponse = campaignManagement.addAdGroups(addAdGroupsRequest); // RemoteException, EditorialApiFaultDetail, AdApiFaultDetail

                        /*
                        result.getAdGroupsResultCollection()[j].setSpecificTrackingId(trackingId);
                        result.getAdGroupsResultCollection()[j].setGxCampaignId(adGroupsRequests[j].getGxCampaignId());
                        result.getAdGroupsResultCollection()[j].setBingCampaignId(adGroupsRequests[j].getBingCampaignId());
                        result.getAdGroupsResultCollection()[j].createAdGroupCollection(addAdGroupsResponse.getAdGroupIds().length);
                        */
                        for (int i=0; i<addAdGroupsResponse.getAdGroupIds().length; i++) {
                            GA_ResultItem resultItem = new GA_ResultItem();
                            resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                            resultItem.CampaignId =  adGroupsRequests[j].getBingCampaignId();
                            resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();
                            resultItem.AdGroupId = addAdGroupsResponse.getAdGroupIds()[i];

                            result.Items.add(resultItem);

                            //result.getAdGroupsResultCollection()[j].addAdGroupResult(i, ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId(), addAdGroupsResponse.getAdGroupIds()[i]);
                        }

                    }else if(chunks > 1){
                        int counter = 1;
                        int index = 0;
                        int chunkItems = 1000;
                        while (counter <= chunks){
                            if(counter == chunks){
                                chunkItems = allAdGroups.length - index;
                            }

                            chunkedAdGroups = new AdGroup[chunkItems];
                            for(int i = 0; i < chunkItems ; i++){
                                chunkedAdGroups[i] = allAdGroups[index];
                                index+=1;
                            }
                            index = counter * 1000;
                            counter++;

                            addAdGroupsRequest.setAdGroups(chunkedAdGroups);

                            addAdGroupsResponse = campaignManagement.addAdGroups(addAdGroupsRequest); // RemoteException, EditorialApiFaultDetail, AdApiFaultDetail

                            /*
                            result.getAdGroupsResultCollection()[j].setSpecificTrackingId(trackingId);
                            result.getAdGroupsResultCollection()[j].setGxCampaignId(adGroupsRequests[j].getGxCampaignId());
                            result.getAdGroupsResultCollection()[j].setBingCampaignId(adGroupsRequests[j].getBingCampaignId());
                            result.getAdGroupsResultCollection()[j].createAdGroupCollection(addAdGroupsResponse.getAdGroupIds().length);
                            */
                            for (int i=0; i<addAdGroupsResponse.getAdGroupIds().length; i++) {

                                GA_ResultItem resultItem = new GA_ResultItem();
                                resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                                resultItem.CampaignId =  adGroupsRequests[j].getBingCampaignId();
                                resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();
                                resultItem.AdGroupId = addAdGroupsResponse.getAdGroupIds()[i];

                                result.Items.add(resultItem);

                                //result.getAdGroupsResultCollection()[j].addAdGroupResult(i, ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId(), addAdGroupsResponse.getAdGroupIds()[i]);
                            }


                        }
                    }

                    // Call succeeded with no errors

                    // Create the return object
                    /*trackingId = stub.getResponseHeader(namespace, "TrackingId").getValue();
                    result.getAdGroupsResultCollection()[j].setSpecificTrackingId(trackingId);
                    result.getAdGroupsResultCollection()[j].setGxCampaignId(adGroupsRequests[j].getGxCampaignId());
                    result.getAdGroupsResultCollection()[j].setBingCampaignId(adGroupsRequests[j].getBingCampaignId());
                    result.getAdGroupsResultCollection()[j].createAdGroupCollection(addAdGroupsResponse.getAdGroupIds().length);
                    for (int i=0; i<addAdGroupsResponse.getAdGroupIds().length; i++) {
                        result.getAdGroupsResultCollection()[j].addAdGroupResult(i, ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId(), addAdGroupsResponse.getAdGroupIds()[i]);
                    }
                    */
                } catch (ApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault, i);

                        resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();

                        result.Items.add(resultItem);
                    }
                } catch (AdApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault);

                        resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();

                        result.Items.add(resultItem);
                    }
                } catch (RemoteException e) { // IN CALL
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(e);

                        resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();

                        result.Items.add(resultItem);
                    }
                }
            }
        } catch (GxException e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        } catch (Exception e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        }

        String returnMessage = null;
        // GxAdGroupsResults -> XML
        try {
            JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class); // JAXBException

            Marshaller marshallerObj = contextObj.createMarshaller(); // JAXBException
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // PropertyException

            StringWriter sw = new StringWriter();

            marshallerObj.marshal(result, sw); // JAXBException
            returnMessage = sw.getBuffer().toString();
        }  catch (PropertyException e) { // AFTER CALL
            returnMessage = util.getPropertyExceptionMessage(e);
        } catch (JAXBException e) { // AFTER CALL
            returnMessage = util.getJAXBExceptionMessage(e);
        }
        return returnMessage;
    }

    public String updateAdGroups(long customerAccountId, String adGroupsRequestsXML) {
        ICampaignManagementService campaignManagement = null;
        CampaignManagementServiceLocator campaignServiceLocator = null;
        BasicHttpBinding_ICampaignManagementServiceStub stub = null;
        UpdateAdGroupsRequest updateAdGroupsRequest = null;
        GA_Result result = new GA_Result();
        Util util = new Util();
        GxAdGroupsRequest[] adGroupsRequests = null;
        try {
            HashMap<String, String> properties = Info.getBingProperties();
            String namespace = properties.get("campaignNamespace");
            String url = properties.get("campaignURL");
            String userName = properties.get("username");
            String password = properties.get("password");
            String developerToken = properties.get("developerToken");
            String customerId = properties.get("customerId");
            String applicationToken = properties.get("applicationToken");

            campaignServiceLocator = new CampaignManagementServiceLocator();
            campaignServiceLocator.setBasicHttpBinding_ICampaignManagementServiceEndpointAddress(url);
            campaignManagement = campaignServiceLocator.getBasicHttpBinding_ICampaignManagementService(); // ServiceException
            stub = (BasicHttpBinding_ICampaignManagementServiceStub) campaignManagement;

            // Set header parameters
            stub.setHeader(namespace, "UserName", userName);
            stub.setHeader(namespace, "Password", password);
            stub.setHeader(namespace, "DeveloperToken", developerToken);
            stub.setHeader(namespace, "CustomerId", customerId);
            stub.setHeader(namespace, "CustomerAccountId", customerAccountId);
            stub.setHeader(namespace, "ApplicationToken", applicationToken);

            // Parse adGroupsRequests from XML
            adGroupsRequests = util.adGroupsRequestsFromXML(adGroupsRequestsXML); // IllegalArgumentException, GxException, ParserConfigurationException, SAXException, IOException
            if (adGroupsRequests.length == 0) {
                throw new GxItemException("No AdGroupsRequests were found");
            }

            for (int j=0; j<adGroupsRequests.length; j++) {
                // Set body parameters
                updateAdGroupsRequest = new UpdateAdGroupsRequest();
                updateAdGroupsRequest.setCampaignId(adGroupsRequests[j].getBingCampaignId());
                updateAdGroupsRequest.setAdGroups(adGroupsRequests[j].getAdGroups());

                try {
                    // Call WS
                    campaignManagement.updateAdGroups(updateAdGroupsRequest); // RemoteException, ApiFaultDetail, AdApiFaultDetail

                    // Call succeeded with no errors

                    // Create the return object

                    /*
                    result.getAdGroupsResultCollection()[j].setSpecificTrackingId(trackingId);
                    result.getAdGroupsResultCollection()[j].setGxCampaignId(adGroupsRequests[j].getGxCampaignId());
                    result.getAdGroupsResultCollection()[j].setBingCampaignId(adGroupsRequests[j].getBingCampaignId());
                    result.getAdGroupsResultCollection()[j].createAdGroupCollection(adGroupsRequests[j].getAdGroups().length);
                    */
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {

                        GA_ResultItem resultItem =  new GA_ResultItem();
                        resultItem.SubCampaignGxId = adGroupsRequests[j].getGxCampaignId();
                        resultItem.CampaignId = adGroupsRequests[j].getBingCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();
                        resultItem.AdGroupId = adGroupsRequests[j].getAdGroups()[i].getId();

                        result.Items.add(resultItem);

                        //result.getAdGroupsResultCollection()[j].addAdGroupResult(i, ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId(), adGroupsRequests[j].getAdGroups()[i].getId());
                    }
                } catch (ApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault, i);

                        resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();

                        result.Items.add(resultItem);
                    }
                } catch (AdApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault);

                        resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();

                        result.Items.add(resultItem);
                    }
                } catch (RemoteException e) { // IN CALL
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(e);

                        resultItem.SubCampaignGxId = adGroupsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();

                        result.Items.add(resultItem);
                    }
                }
            }
        } catch (GxException e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        } catch (Exception e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        }

        String returnMessage = null;
        // GxAdGroupsResults -> XML
        try {
            JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class); // JAXBException

            Marshaller marshallerObj = contextObj.createMarshaller(); // JAXBException
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // PropertyException

            StringWriter sw = new StringWriter();

            marshallerObj.marshal(result, sw); // JAXBException
            returnMessage = sw.getBuffer().toString();
        }  catch (PropertyException e) { // AFTER CALL
            returnMessage = util.getPropertyExceptionMessage(e);
        } catch (JAXBException e) { // AFTER CALL
            returnMessage = util.getJAXBExceptionMessage(e);
        }
        return returnMessage;
    }

    public String setNegativeKeywordsToAdGroups(long customerAccountId, String adGroupNegativeKeywordsRequestsXML) {
        ICampaignManagementService campaignManagement = null;
        CampaignManagementServiceLocator campaignServiceLocator = null;
        BasicHttpBinding_ICampaignManagementServiceStub stub = null;
        SetNegativeKeywordsToAdGroupsRequest setNegativeKeywordsToAdGroupsRequest = null;
        GA_Result result = new GA_Result();
        Util util = new Util();
        GxAdGroupNegativeKeywordsRequest[] adGroupNegativeKeywordsRequests = null;
        try {
            HashMap<String, String> properties = Info.getBingProperties();
            String namespace = properties.get("campaignNamespace");
            String url = properties.get("campaignURL");
            String userName = properties.get("username");
            String password = properties.get("password");
            String developerToken = properties.get("developerToken");
            String customerId = properties.get("customerId");
            String applicationToken = properties.get("applicationToken");

            campaignServiceLocator = new CampaignManagementServiceLocator();
            campaignServiceLocator.setBasicHttpBinding_ICampaignManagementServiceEndpointAddress(url);
            campaignManagement = campaignServiceLocator.getBasicHttpBinding_ICampaignManagementService(); // ServiceException
            stub = (BasicHttpBinding_ICampaignManagementServiceStub) campaignManagement;

            // Set header parameters
            stub.setHeader(namespace, "UserName", userName);
            stub.setHeader(namespace, "Password", password);
            stub.setHeader(namespace, "DeveloperToken", developerToken);
            stub.setHeader(namespace, "CustomerId", customerId);
            stub.setHeader(namespace, "CustomerAccountId", customerAccountId);
            stub.setHeader(namespace, "ApplicationToken", applicationToken);

            // Parse adGroupNegativeKeywordsRequests from XML
            adGroupNegativeKeywordsRequests = util.adGroupNegativeKeywordsRequestsFromXML(adGroupNegativeKeywordsRequestsXML); // IllegalArgumentException, GxException, ParserConfigurationException, SAXException, IOException
            if (adGroupNegativeKeywordsRequests.length == 0) {
                throw new GxItemException("No AdGroupNegativeKeywordsRequests were found");
            }

            for (int j=0; j<adGroupNegativeKeywordsRequests.length; j++) {
                // Set body parameters
                setNegativeKeywordsToAdGroupsRequest = new SetNegativeKeywordsToAdGroupsRequest();
                setNegativeKeywordsToAdGroupsRequest.setCampaignId(adGroupNegativeKeywordsRequests[j].getBingCampaignId());
                setNegativeKeywordsToAdGroupsRequest.setAdGroupNegativeKeywords(adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords());

                try {
                    // Call WS
                    campaignManagement.setNegativeKeywordsToAdGroups(setNegativeKeywordsToAdGroupsRequest); // RemoteException, ApiFaultDetail, AdApiFaultDetail

                    // Call succeeded with no errors

                    // Create the return object

                    /*
                    result.getAdGroupsResultCollection()[j].setSpecificTrackingId(trackingId);
                    result.getAdGroupsResultCollection()[j].setGxCampaignId(adGroupNegativeKeywordsRequests[j].getGxCampaignId());
                    result.getAdGroupsResultCollection()[j].setBingCampaignId(adGroupNegativeKeywordsRequests[j].getBingCampaignId());
                    result.getAdGroupsResultCollection()[j].createAdGroupCollection(adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords().length);
                    */
                    for (int i=0; i<adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords().length; i++) {
                        GA_ResultItem resultItem =  new GA_ResultItem();
                        resultItem.SubCampaignGxId = adGroupNegativeKeywordsRequests[j].getGxCampaignId();
                        resultItem.CampaignId = adGroupNegativeKeywordsRequests[j].getBingCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroupNegativeKeywords) adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords()[i]).getGxAdGroupId();
                        resultItem.AdGroupGxId = adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords()[i].getAdGroupId();

                        result.Items.add(resultItem);

                    }
                } catch (ApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault, i);

                        resultItem.SubCampaignGxId =  adGroupNegativeKeywordsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroupNegativeKeywords) adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords()[i]).getGxAdGroupId();

                        result.Items.add(resultItem);
                    }
                } catch (AdApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault);

                        resultItem.SubCampaignGxId =  adGroupNegativeKeywordsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroupNegativeKeywords) adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords()[i]).getGxAdGroupId();

                        result.Items.add(resultItem);
                    }
                } catch (RemoteException e) { // IN CALL
                    for (int i=0; i<adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(e);

                        resultItem.SubCampaignGxId =  adGroupNegativeKeywordsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroupNegativeKeywords) adGroupNegativeKeywordsRequests[j].getAdGroupNegativeKeywords()[i]).getGxAdGroupId();

                        result.Items.add(resultItem);
                    }
                }
            }
        } catch (GxException e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        } catch (Exception e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        }

        String returnMessage = null;
        // GxAdGroupsResults -> XML
        try {
            JAXBContext contextObj = JAXBContext.newInstance(GxAdGroupsResults.class); // JAXBException

            Marshaller marshallerObj = contextObj.createMarshaller(); // JAXBException
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // PropertyException

            StringWriter sw = new StringWriter();

            marshallerObj.marshal(result, sw); // JAXBException
            returnMessage = sw.getBuffer().toString();
        }  catch (PropertyException e) { // AFTER CALL
            returnMessage = util.getPropertyExceptionMessage(e);
        } catch (JAXBException e) { // AFTER CALL
            returnMessage = util.getJAXBExceptionMessage(e);
        }
        return returnMessage;
    }

    public String setNegativeSitesToAdGroups(long customerAccountId, String adGroupNegativeSitesRequestsXML) {
        ICampaignManagementService campaignManagement = null;
        CampaignManagementServiceLocator campaignServiceLocator = null;
        BasicHttpBinding_ICampaignManagementServiceStub stub = null;
        SetNegativeSitesToAdGroupsRequest setNegativeSitesToAdGroupsRequest = null;
        GA_Result result = new GA_Result();
        Util util = new Util();
        GxAdGroupNegativeSitesRequest[] adGroupNegativeSitesRequests = null;
        try {
            HashMap<String, String> properties = Info.getBingProperties();
            String namespace = properties.get("campaignNamespace");
            String url = properties.get("campaignURL");
            String userName = properties.get("username");
            String password = properties.get("password");
            String developerToken = properties.get("developerToken");
            String customerId = properties.get("customerId");
            String applicationToken = properties.get("applicationToken");

            campaignServiceLocator = new CampaignManagementServiceLocator();
            campaignServiceLocator.setBasicHttpBinding_ICampaignManagementServiceEndpointAddress(url);
            campaignManagement = campaignServiceLocator.getBasicHttpBinding_ICampaignManagementService(); // ServiceException
            stub = (BasicHttpBinding_ICampaignManagementServiceStub) campaignManagement;

            // Set header parameters
            stub.setHeader(namespace, "UserName", userName);
            stub.setHeader(namespace, "Password", password);
            stub.setHeader(namespace, "DeveloperToken", developerToken);
            stub.setHeader(namespace, "CustomerId", customerId);
            stub.setHeader(namespace, "CustomerAccountId", customerAccountId);
            stub.setHeader(namespace, "ApplicationToken", applicationToken);

            // Parse adGroupNegativeSitesRequests from XML
            adGroupNegativeSitesRequests = util.adGroupNegativeSitesRequestsFromXML(adGroupNegativeSitesRequestsXML); // IllegalArgumentException, GxException, ParserConfigurationException, SAXException, IOException
            if (adGroupNegativeSitesRequests.length == 0) {
                throw new GxItemException("No AdGroupNegativeSitesRequests were found");
            }

            for (int j=0; j<adGroupNegativeSitesRequests.length; j++) {
                // Set body parameters
                setNegativeSitesToAdGroupsRequest = new SetNegativeSitesToAdGroupsRequest();
                setNegativeSitesToAdGroupsRequest.setCampaignId(adGroupNegativeSitesRequests[j].getBingCampaignId());
                setNegativeSitesToAdGroupsRequest.setAdGroupNegativeSites(adGroupNegativeSitesRequests[j].getAdGroupNegativeSites());

                try {
                    // Call WS
                    campaignManagement.setNegativeSitesToAdGroups(setNegativeSitesToAdGroupsRequest); // RemoteException, ApiFaultDetail, AdApiFaultDetail

                    // Call succeeded with no errors

                    // Create the return object

                    /*
                    result.getAdGroupsResultCollection()[j].setSpecificTrackingId(trackingId);
                    result.getAdGroupsResultCollection()[j].setGxCampaignId(adGroupNegativeSitesRequests[j].getGxCampaignId());
                    result.getAdGroupsResultCollection()[j].setBingCampaignId(adGroupNegativeSitesRequests[j].getBingCampaignId());
                    result.getAdGroupsResultCollection()[j].createAdGroupCollection(adGroupNegativeSitesRequests[j].getAdGroupNegativeSites().length);
                    */

                    for (int i=0; i<adGroupNegativeSitesRequests[j].getAdGroupNegativeSites().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem();
                        resultItem.SubCampaignGxId =  adGroupNegativeSitesRequests[j].getGxCampaignId();
                        resultItem.CampaignId =  adGroupNegativeSitesRequests[j].getBingCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroupNegativeSites) adGroupNegativeSitesRequests[j].getAdGroupNegativeSites()[i]).getGxAdGroupId();
                        resultItem.AdGroupId = adGroupNegativeSitesRequests[j].getAdGroupNegativeSites()[i].getAdGroupId();

                        //result.getAdGroupsResultCollection()[j].addAdGroupResult(i, ((GxAdGroupNegativeSites) adGroupNegativeSitesRequests[j].getAdGroupNegativeSites()[i]).getGxAdGroupId(), adGroupNegativeSitesRequests[j].getAdGroupNegativeSites()[i].getAdGroupId());

                        result.Items.add(resultItem);
                    }
                } catch (ApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupNegativeSitesRequests[j].getAdGroupNegativeSites().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault, i);

                        resultItem.SubCampaignGxId =  adGroupNegativeSitesRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroupNegativeSites) adGroupNegativeSitesRequests[j].getAdGroupNegativeSites()[i]).getGxAdGroupId();

                        result.Items.add(resultItem);
                    }
                } catch (AdApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupNegativeSitesRequests[j].getAdGroupNegativeSites().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault);

                        resultItem.SubCampaignGxId =  adGroupNegativeSitesRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroupNegativeSites) adGroupNegativeSitesRequests[j].getAdGroupNegativeSites()[i]).getGxAdGroupId();

                        result.Items.add(resultItem);
                    }
                } catch (RemoteException e) { // IN CALL
                    for (int i=0; i<adGroupNegativeSitesRequests[j].getAdGroupNegativeSites().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(e);

                        resultItem.SubCampaignGxId =  adGroupNegativeSitesRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroupNegativeSites) adGroupNegativeSitesRequests[j].getAdGroupNegativeSites()[i]).getGxAdGroupId();

                        result.Items.add(resultItem);
                    }
                }
            }
        } catch (GxException e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        } catch (Exception e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        }

        String returnMessage = null;
        // GxAdGroupsResults -> XML
        try {
            JAXBContext contextObj = JAXBContext.newInstance(GxAdGroupsResults.class); // JAXBException

            Marshaller marshallerObj = contextObj.createMarshaller(); // JAXBException
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // PropertyException

            StringWriter sw = new StringWriter();

            marshallerObj.marshal(result, sw); // JAXBException
            returnMessage = sw.getBuffer().toString();
        }  catch (PropertyException e) { // AFTER CALL
            returnMessage = util.getPropertyExceptionMessage(e);
        } catch (JAXBException e) { // AFTER CALL
            returnMessage = util.getJAXBExceptionMessage(e);
        }
        return returnMessage;
    }

    public String deleteAdGroups(long customerAccountId, String adGroupsRequestsXML) {
        ICampaignManagementService campaignManagement = null;
        CampaignManagementServiceLocator campaignServiceLocator = null;
        BasicHttpBinding_ICampaignManagementServiceStub stub = null;
        DeleteAdGroupsRequest deleteAdGroupsRequest = null;
        GA_Result result = new GA_Result();
        Util util = new Util();
        GxAdGroupsRequest[] adGroupsRequests = null;
        long[] adGroupIds = null;
        try {
            HashMap<String, String> properties = Info.getBingProperties();
            String namespace = properties.get("campaignNamespace");
            String url = properties.get("campaignURL");
            String userName = properties.get("username");
            String password = properties.get("password");
            String developerToken = properties.get("developerToken");
            String customerId = properties.get("customerId");
            String applicationToken = properties.get("applicationToken");

            campaignServiceLocator = new CampaignManagementServiceLocator();
            campaignServiceLocator.setBasicHttpBinding_ICampaignManagementServiceEndpointAddress(url);
            campaignManagement = campaignServiceLocator.getBasicHttpBinding_ICampaignManagementService(); // ServiceException
            stub = (BasicHttpBinding_ICampaignManagementServiceStub) campaignManagement;

            // Set header parameters
            stub.setHeader(namespace, "UserName", userName);
            stub.setHeader(namespace, "Password", password);
            stub.setHeader(namespace, "DeveloperToken", developerToken);
            stub.setHeader(namespace, "CustomerId", customerId);
            stub.setHeader(namespace, "CustomerAccountId", customerAccountId);
            stub.setHeader(namespace, "ApplicationToken", applicationToken);

            // Parse adGroupsRequests from XML
            adGroupsRequests = util.adGroupsRequestsFromXML(adGroupsRequestsXML); // IllegalArgumentException, GxException, ParserConfigurationException, SAXException, IOException
            if (adGroupsRequests.length == 0) {
                throw new GxItemException("No AdGroupsRequests were found");
            }

            //result = new GxAdGroupsResults(adGroupsRequests.length);

            for (int j=0; j<adGroupsRequests.length; j++) {
                // Set body parameters
                adGroupIds = new long[adGroupsRequests[j].getAdGroups().length];
                for (int i=0; i<adGroupIds.length; i++) {
                    if (adGroupsRequests[j].getAdGroups()[i].getId() == null) {
                        adGroupIds[i] = -1;
                    } else {
                        adGroupIds[i] = adGroupsRequests[j].getAdGroups()[i].getId();
                    }
                }
                deleteAdGroupsRequest = new DeleteAdGroupsRequest();
                deleteAdGroupsRequest.setCampaignId(adGroupsRequests[j].getBingCampaignId());
                deleteAdGroupsRequest.setAdGroupIds(adGroupIds);

                try {
                    // Call WS
                    campaignManagement.deleteAdGroups(deleteAdGroupsRequest); // RemoteException, ApiFaultDetail, AdApiFaultDetail

                    // Call succeeded with no errors

                    // Create the return object

                    /*
                    result.getAdGroupsResultCollection()[j].setSpecificTrackingId(trackingId);
                    result.getAdGroupsResultCollection()[j].setGxCampaignId(adGroupsRequests[j].getGxCampaignId());
                    result.getAdGroupsResultCollection()[j].setBingCampaignId(adGroupsRequests[j].getBingCampaignId());
                    result.getAdGroupsResultCollection()[j].createAdGroupCollection(adGroupsRequests[j].getAdGroups().length);
                    */
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem();
                        resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                        resultItem.CampaignId = adGroupsRequests[j].getBingCampaignId();
                        resultItem.AdGroupGxId = resultItem.AdGroupId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();
                        resultItem.AdGroupId = adGroupsRequests[j].getAdGroups()[i].getId();

                        result.Items.add(resultItem);

                        //result.getAdGroupsResultCollection()[j].addAdGroupResult(i, ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId(), adGroupsRequests[j].getAdGroups()[i].getId());

                    }
                } catch (ApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault, i);

                        resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();

                        result.Items.add(resultItem);
                    }
                } catch (AdApiFaultDetail fault) { // IN CALL
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(fault);

                        resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();

                        result.Items.add(resultItem);
                    }
                } catch (RemoteException e) { // IN CALL
                    for (int i=0; i<adGroupsRequests[j].getAdGroups().length; i++) {
                        GA_ResultItem resultItem = new GA_ResultItem(e);

                        resultItem.SubCampaignGxId =  adGroupsRequests[j].getGxCampaignId();
                        resultItem.AdGroupGxId = ((GxAdGroup) adGroupsRequests[j].getAdGroups()[i]).getGxId();

                        result.Items.add(resultItem);
                    }
                }
            }
        } catch (GxException e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        } catch (Exception e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        }

        String returnMessage = null;
        // GxAdGroupsResults -> XML
        try {
            JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class); // JAXBException

            Marshaller marshallerObj = contextObj.createMarshaller(); // JAXBException
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // PropertyException

            StringWriter sw = new StringWriter();

            marshallerObj.marshal(result, sw); // JAXBException
            returnMessage = sw.getBuffer().toString();
        }  catch (PropertyException e) { // AFTER CALL
            returnMessage = util.getPropertyExceptionMessage(e);
        } catch (JAXBException e) { // AFTER CALL
            returnMessage = util.getJAXBExceptionMessage(e);
        }
        return returnMessage;
    }
}
